/*
 * 1、现用http://tool.chinaz.com/js.aspx加密压缩
 * 2、再用http://tool.chinaz.com/tools/jscodeconfusion.aspx代码混淆
 */

var board = new Array();
var RiLeGoScore = 0;
var hasConflicted = new Array();
var winOnce = true;
$(document).ready(function () {
	//加载调用的方法
	prepareForMobile();
	newgame();
	hideDialog();
});

function hideDialog() {
	$(".dialog-success").css("display", "none");
	$(".dialog-fail").css("display", "none");
}

function prepareForMobile() {
	if (isPC()) {
		gridContainerWidth = 500;
		cellSpace = 20;
		cellSideLength = 100;
	}
	$("#grid-container").css('width', gridContainerWidth - 2 * cellSpace);
	$("#grid-container").css('height', gridContainerWidth - 2 * cellSpace);
	$("#grid-container").css('padding', cellSpace);
	$("#grid-container").css('border-radius', 0.02 * gridContainerWidth);
	if (documentHeight * 3 / documentWidth > 5) {
		$('header').css('margin-top', cellSideLength);
	}
	$(".grid-cell").css("width", cellSideLength);
	$(".grid-cell").css("height", cellSideLength);
	$(".grid-cell").css("border-radius", 0.02 * cellSideLength);
}

function newgame() {
	//初始化棋盘
	init();
	//随机生成两个数字
	generateOneNumber();
	generateOneNumber();
	resetSocre();
}

function again() {
	newgame();
	hideDialog();
	resetSocre();
}

function conti() {
	hideDialog();
}

function init() {
	for (var i = 0; i < 4; i++) {
		for (var j = 0; j < 4; j++) {
			var gridCell = $("#grid-cell-" + i + "-" + j);
			gridCell.css("top", getPosTop(i, j));
			gridCell.css("left", getPosLeft(i, j));
		}
	}
	for (var i = 0; i < 4; i++) {
		board[i] = new Array();
		hasConflicted[i] = new Array();
		for (var j = 0; j < 4; j++) {
			board[i][j] = 0;
			hasConflicted[i][j] = false;
		}
	}
	winOnce = true;//不提示输赢时为TRUE，否则为FALSE
	RiLeGoScore = 0;
	FangZuoBi = 0;
	WoCao = 0;
	updateBoardView();
}

function updateBoardView() {
	//移除class为number-cell的元素
	$(".number-cell").remove();
	for (var i = 0; i < 4; i++) {
		for (var j = 0; j < 4; j++) {
			//append方法在元素的内部结尾添加代码
			$("#grid-container").append('<div class = "number-cell" id = "number-cell-' + i + '-' + j + '"></div>');
			//取得id为number-cell-i-j的元素
			var theNumberCell = $('#number-cell-' + i + "-" + j);

			if (board[i][j] == 0) {
				theNumberCell.css("width", "0px");
				theNumberCell.css("height", "0px");
				theNumberCell.css("top", getPosTop(i, j) + cellSideLength / 2);
				theNumberCell.css("left", getPosLeft(i, j) + cellSideLength / 2);
			} else {
				theNumberCell.css("width", cellSideLength + "px");
				theNumberCell.css("height", cellSideLength + "px");
				theNumberCell.css("top", getPosTop(i, j));
				theNumberCell.css("left", getPosLeft(i, j));
				theNumberCell.css("background-color", getNumberCellBgColor(board[i][j]));
				theNumberCell.css("color", getNumberCellFontColor(board[i][j]));
				theNumberCell.css("font-size", getNumberCellFontSize(board[i][j]));
				//改变元素的内部文本内容
				theNumberCell.text(board[i][j]);
			}

			hasConflicted[i][j] = false;
		}
	}
	$('.number-cell').css('line-height', cellSideLength + "px");

}

function generateOneNumber() {
	if (nospace(board)) {
		return false;
	}
	//随机找到一个位置
	var randomX = parseInt(Math.floor(Math.random() * 4));
	var randomY = parseInt(Math.floor(Math.random() * 4));

	while (true) {
		if (board[randomX][randomY] == 0) {
			//证明当前位置可用
			break;
		}
		var randomX = parseInt(Math.floor(Math.random() * 4));
		var randomY = parseInt(Math.floor(Math.random() * 4));
	}
	//随机生成一个数字
	var randomNumber = Math.random() < 0.5 ? 2 : 4;
	//显示随机数字
	board[randomX][randomY] = randomNumber;
	showNumberWithAnimation(randomX, randomY, randomNumber);

	return true;
}

$(document).keydown(function (event) {

	switch (event.keyCode) {
		case 37: //左
			event.preventDefault();
			if (moveLeft()) {
				setTimeout("generateOneNumber()", 0);
				setTimeout("isGameover()", 0);
				setTimeout("isWin()", 0);
			}
			break;
		case 38: //上
			event.preventDefault();
			if (moveUp()) {
				setTimeout("generateOneNumber()", 0);
				setTimeout("isGameover()", 0);
				setTimeout("isWin()", 0);
			}
			break;
		case 39: //右
			event.preventDefault();
			if (moveRight()) {
				setTimeout("generateOneNumber()", 0);
				setTimeout("isGameover()", 0);
				setTimeout("isWin()", 0);
			}
			break;
		case 40: //下
			event.preventDefault();
			if (moveDown()) {
				setTimeout("generateOneNumber()", 0);
				setTimeout("isGameover()", 0);
				setTimeout("isWin()", 0);
			}
			break;
		default:
			return;
	}
});

document.addEventListener('touchstart', function (event) {
	startx = event.touches[0].pageX;
	starty = event.touches[0].pageY;
});

document.addEventListener('touchmove', function (event) {
	event.preventDefault();
});

document.addEventListener('touchend', function (event) {
	endx = event.changedTouches[0].pageX;
	endy = event.changedTouches[0].pageY;

	var deltax = endx - startx;
	var deltay = endy - starty;

	if (Math.abs(deltax) < 0.2 * documentWidth && Math.abs(deltay) < 0.2 * documentWidth) {
		return;
	}

	if (Math.abs(deltax) >= Math.abs(deltay)) {
		if (deltax > 0) {
			//向右
			if (moveRight()) {
				setTimeout("generateOneNumber()", 0);
				setTimeout("isGameover()", 0);
				setTimeout("isWin()", 0);
			}
		} else {
			//向左
			if (moveLeft()) {
				setTimeout("generateOneNumber()", 0);
				setTimeout("isGameover()", 0);
				setTimeout("isWin()", 0);
			}
		}
	} else {
		if (deltay > 0) {
			//向下
			if (moveDown()) {
				setTimeout("generateOneNumber()", 0);
				setTimeout("isGameover()", 0);
				setTimeout("isWin()", 0);
			}
		} else {
			//向上
			if (moveUp()) {
				setTimeout("generateOneNumber()", 0);
				setTimeout("isGameover()", 0);
				setTimeout("isWin()", 0);
			}
		}
	}
});

function md5(str, raw) {
	var hexcase = 0;
	var chrsz = 8;
	str = utf16to8(str);

	function utf16to8(str) {
		var out, i, len, c;
		out = "";
		len = str.length;
		for (i = 0; i < len; i++) {
			c = str.charCodeAt(i);
			if ((c >= 0x0001) && (c <= 0x007F)) {
				out += str.charAt(i);
			} else if (c > 0x07FF) {
				out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
				out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
				out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
			} else {
				out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
				out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
			}
		}
		return out;
	}

	function hex_md5(s) {
		return binb2hex(core_md5(str2binb(s), s.length * chrsz));
	}

	function str_md5(s) {
		return binb2str(core_md5(str2binb(s), s.length * chrsz));
	}

	function binb2hex(binarray) {
		var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
		var str = "";
		for (var i = 0; i < binarray.length * 4; i++) {
			str += hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) +
					hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xF);
		}
		return str;
	}

	function binb2str(bin) {
		var str = "";
		var mask = (1 << chrsz) - 1;
		for (var i = 0; i < bin.length * 32; i += chrsz)
			str += String.fromCharCode((bin[i >> 5] >>> (32 - chrsz - i % 32)) & mask);
		return str;
	}

	function str2binb(str) {
		var bin = Array();
		var mask = (1 << chrsz) - 1;
		for (var i = 0; i < str.length * chrsz; i += chrsz)
			bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i % 32);
		return bin;
	}

	function safe_add(x, y) {
		var lsw = (x & 0xFFFF) + (y & 0xFFFF);
		var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
		return (msw << 16) | (lsw & 0xFFFF);
	}

	function rol(num, cnt) {
		return (num << cnt) | (num >>> (32 - cnt));
	}

	function md5_ft(t, b, c, d) {
		if (t < 20)
			return (b & c) | ((~b) & d);
		if (t < 40)
			return b ^ c ^ d;
		if (t < 60)
			return (b & c) | (b & d) | (c & d);
		return b ^ c ^ d;
	}

	function md5_kt(t) {
		return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;
	}

	function core_md5(x, len) {
		x[len >> 5] |= 0x80 << (24 - len % 32);
		x[((len + 64 >> 9) << 4) + 15] = len;

		var w = Array(80);
		var a = 1732584193;
		var b = -271733879;
		var c = -1732584194;
		var d = 271733878;
		var e = -1009589776;

		for (var i = 0; i < x.length; i += 16) {
			var olda = a;
			var oldb = b;
			var oldc = c;
			var oldd = d;
			var olde = e;

			for (var j = 0; j < 80; j++) {
				if (j < 16)
					w[j] = x[i + j];
				else
					w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
				var t = safe_add(safe_add(rol(a, 5), md5_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), md5_kt(j)));
				e = d;
				d = c;
				c = rol(b, 30);
				b = a;
				a = t;
			}

			a = safe_add(a, olda);
			b = safe_add(b, oldb);
			c = safe_add(c, oldc);
			d = safe_add(d, oldd);
			e = safe_add(e, olde);
		}
		return Array(a, b, c, d, e);
	}

	if (raw == true) {
		return str_md5(str);
	} else {
		return hex_md5(str);
	}
}

function isGameover() {
	if (nospace(board) && nomove(board)) {
		gameover();
	}
}

function isWin() {
	for (var j = 0; j < 4; j++) {
		for (var i = 1; i < 4; i++) {
			if (board[i][j] == 2048) {
				if (winOnce == false) {
					win();
					winOnce = true;
				}
			}
		}
	}
	return false;
}

/*
 ** randomWord 产生任意长度随机字母数字组合
 ** randomFlag-是否任意长度 min-任意长度最小位[固定位数] max-任意长度最大位
 ** xuanfeng 2014-08-28
 */

function randomWord(randomFlag, min, max) {
	var str = "",
			range = min,
			arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

	// 随机产生
	if (randomFlag) {
		range = Math.round(Math.random() * (max - min)) + min;
	}
	for (var i = 0; i < range; i++) {
		pos = Math.round(Math.random() * (arr.length - 1));
		str += arr[pos];
	}
	return str;
}

function win() {
	$(".dialog-success").css("display", "block");
	var randstr = randomWord(false, 32);
	var over = 1;
	var FangZuoBiScores = FangZuoBi;
	var RiLeGoScores = RiLeGoScore;
	var token = md5(FangZuoBi + randstr);
	var rand = randstr;
	var json = "{\"over\":\"" + over + "\",\"FangZuoBiScores\":\"" + FangZuoBiScores + "\",\"RiLeGoScores\":\"" + RiLeGoScores + "\",\"token\":\"" + token + "\",\"rand\":\"" + rand + "\"}";
	var key = window.btoa(json);
	$.post('2048score.php', {r: key});
}

function gameover() {
	$(".dialog-fail").css("display", "block");
	var randstr = randomWord(false, 32);
	var over = 1;
	var FangZuoBiScores = FangZuoBi;
	var RiLeGoScores = RiLeGoScore;
	var token = md5(FangZuoBi + randstr);
	var rand = randstr;
	var json = "{\"over\":\"" + over + "\",\"FangZuoBiScores\":\"" + FangZuoBiScores + "\",\"RiLeGoScores\":\"" + RiLeGoScores + "\",\"token\":\"" + token + "\",\"rand\":\"" + rand + "\"}";
	var key = window.btoa(json);
	$.post('2048score.php', {r: key});
}

function moveUp() {
	if (!canMoveUp(board)) {
		return false;
	}
	for (var j = 0; j < 4; j++) {
		for (var i = 1; i < 4; i++) {
			if (board[i][j] != 0) {
				//不等于0说明可能向右移动
				for (var k = 0; k < i; k++) {
					if (board[k][j] == 0 && noUpBlock(i, j, k, board)) {
						//可以移动
						showMoveAnimation(i, j, k, j);
						board[k][j] = board[i][j];
						board[i][j] = 0;
						continue;
					} else if (board[k][j] == board[i][j] && noUpBlock(i, j, k, board) && !hasConflicted[k][j]) {
						//可以移动
						//两数相加
						showMoveAnimation(i, j, k, j);
						board[k][j] += board[i][j];
						board[i][j] = 0;
						//加分
						RiLeGoScore += board[k][j];
						FangZuoBi += board[k][j];
						//WoCao = board[k][j];
						//var rank = window.btoa(WoCao);
						//$.post('2048security.php', {z: rank});
						setTimeout("changeScore(RiLeGoScore)", 0);
						hasConflicted[k][j] = true;
						continue;
					}
				}
			}
		}
	}
	setTimeout("updateBoardView()", 0);
	return true;
}

function moveDown() {
	if (!canMoveDown(board)) {
		return false;
	}
	for (var j = 0; j < 4; j++) {
		for (var i = 2; i >= 0; i--) {
			if (board[i][j] != 0) {
				//不等于0说明可能向右移动
				for (var k = 3; k > i; k--) {
					if (board[k][j] == 0 && noDownBlock(i, j, k, board)) {
						//可以移动
						showMoveAnimation(i, j, k, j);
						board[k][j] = board[i][j];
						board[i][j] = 0;
						continue;
					} else if (board[k][j] == board[i][j] && noDownBlock(i, j, k, board) && !hasConflicted[k][j]) {
						//可以移动
						//两数相加
						showMoveAnimation(i, j, k, j);
						board[k][j] += board[i][j];
						board[i][j] = 0;
						//加分
						RiLeGoScore += board[k][j];
						FangZuoBi += board[k][j];
						//WoCao = board[k][j];
						//var rank = window.btoa(WoCao);
						//$.post('2048security.php', {z: rank});
						setTimeout("changeScore(RiLeGoScore)", 0);
						hasConflicted[k][j] = true;
						continue;
					}
				}
			}
		}
	}
	setTimeout("updateBoardView()", 0);
	return true;
}

function moveRight() {
	if (!canMoveRight(board)) {
		return false;
	}
	for (var i = 0; i < 4; i++) {
		for (var j = 2; j >= 0; j--) {
			if (board[i][j] != 0) {
				//不等于0说明可能向右移动
				for (var k = 3; k > j; k--) {
					if (board[i][k] == 0 && noRightBlock(i, j, k, board)) {
						//可以移动
						showMoveAnimation(i, j, i, k);
						board[i][k] = board[i][j];
						board[i][j] = 0;
						continue;
					} else if (board[i][k] == board[i][j] && noRightBlock(i, j, k, board) && !hasConflicted[i][k]) {
						//可以移动
						//两数相加
						showMoveAnimation(i, j, i, k);
						board[i][k] += board[i][j];
						board[i][j] = 0;
						//加分
						RiLeGoScore += board[i][k];
						FangZuoBi += board[i][k];
						//WoCao = board[i][k];
						//var rank = window.btoa(WoCao);
						//$.post('2048security.php', {z: rank});
						setTimeout("changeScore(RiLeGoScore)", 0);
						hasConflicted[i][k] = true;
						continue;
					}
				}
			}
		}
	}
	setTimeout("updateBoardView()", 0);
	return true;
}

function moveLeft() {
	if (!canMoveLeft(board)) {
		return false;
	}
	for (var i = 0; i < 4; i++) {
		for (var j = 1; j < 4; j++) {
			if (board[i][j] != 0) {
				//不等于0说明可能向左移动
				for (var k = 0; k < j; k++) {
					if (board[i][k] == 0 && noLeftBlock(i, j, k, board)) {
						//可以移动
						showMoveAnimation(i, j, i, k);
						board[i][k] = board[i][j];
						board[i][j] = 0;
						continue;
					} else if (board[i][k] == board[i][j] && noLeftBlock(i, j, k, board) && !hasConflicted[i][k]) {
						//可以移动
						//两数相加
						showMoveAnimation(i, j, i, k);
						board[i][k] += board[i][j];
						board[i][j] = 0;
						//加分
						RiLeGoScore += board[i][k];
						FangZuoBi += board[i][k];
						//WoCao = board[i][k];
						//var rank = window.btoa(WoCao);
						//$.post('2048security.php', {z: rank});
						setTimeout("changeScore(RiLeGoScore)", 0);
						hasConflicted[i][k] = true;
						continue;
					}
				}
			}
		}
	}
	setTimeout("updateBoardView()", 0);
	return true;
}